prometheus-node-exporter-lua: fix hostapd_ubus_stations & hostapd_stations
authorMichael Payne <[email protected]>
Mon, 31 Mar 2025 09:30:49 +0000 (09:30 +0000)
committerEtienne Champetier <[email protected]>
Mon, 23 Jun 2025 11:50:18 +0000 (14:50 +0300)
hostapd exposes the `hostapd-auth` ubus object. In both
hostapd_ubus_stations.lua and hostapd_stations.lua this object is
incorrectly matched as if it were a wifi phy such as `hostapd.phy0-ap0`.
Using the literal period to find interfaces (^hostapd%.) instead of the
pattern-matching period (hostapd.) fixes this.

fix formatting consistency

Signed-off-by: Michael Payne <[email protected]>
[fix version conflict]
Signed-off-by: Etienne Champetier <[email protected]>
utils/prometheus-node-exporter-lua/Makefile
utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/hostapd_stations.lua
utils/prometheus-node-exporter-lua/files/usr/lib/lua/prometheus-collectors/hostapd_ubus_stations.lua

index a0f89ae35b7bb619cb8ef0197d69f0d3f7c06a72..bcaf7e019edf253529fd35ac7be3b216cf58d6f6 100644 (file)
@@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=prometheus-node-exporter-lua
 PKG_VERSION:=2025.06.23
-PKG_RELEASE:=3
+PKG_RELEASE:=4
 
 PKG_MAINTAINER:=Etienne CHAMPETIER <[email protected]>
 PKG_LICENSE:=Apache-2.0
index 86b406c8a074a3bc20b3ea813e9a29bd0f5bf88d..dd73e47db73cf155e83f2e852f43b336c7bf39bf 100644 (file)
@@ -1,24 +1,26 @@
-local ubus = require "ubus"
-local bit32 = require "bit32"
+local ubus = require("ubus")
+local bit32 = require("bit32")
 
 local function get_wifi_interfaces()
   local conn = ubus.connect()
   local ubuslist = conn:objects()
   local interfaces = {}
 
-  for _,net in ipairs(ubuslist) do
-    if net.find(net,"hostapd.") then
-      local ifname = net:gsub("hostapd.", "")
-      table.insert(interfaces, ifname);
+  for _, net in ipairs(ubuslist) do
+    if net:find("^hostapd%.") then
+      local ifname = net:gsub("hostapd%.", "")
+      table.insert(interfaces, ifname)
     end
   end
   conn:close()
-  return interfaces;
+  return interfaces
 end
 
 local function is_ubus_interface(ubus_interfaces, interface)
-  for i=1,#ubus_interfaces do
-    if ubus_interfaces[i] == interface then return true end
+  for i = 1, #ubus_interfaces do
+    if ubus_interfaces[i] == interface then
+      return true
+    end
   end
   return false
 end
@@ -30,11 +32,10 @@ local function get_wifi_interface_labels()
   local ubus_interfaces = get_wifi_interfaces()
 
   for _, dev_table in pairs(status) do
-    for _, intf in ipairs(dev_table['interfaces']) do
-      if is_ubus_interface(ubus_interfaces, intf['ifname']) then
-
+    for _, intf in ipairs(dev_table["interfaces"]) do
+      if is_ubus_interface(ubus_interfaces, intf["ifname"]) then
         -- Migrate this to ubus interface once it exposes all interesting labels
-        local handle = io.popen("hostapd_cli -i " .. intf['ifname'] .." status")
+        local handle = io.popen("hostapd_cli -i " .. intf["ifname"] .. " status")
         local hostapd_status = handle:read("*a")
         handle:close()
 
@@ -48,7 +49,7 @@ local function get_wifi_interface_labels()
             hostapd["channel"] = value
           -- hostapd gives us all bss on the relevant phy, find the one we're interested in
           elseif string.match(name, "bss%[%d%]") then
-            if value == intf['ifname'] then
+            if value == intf["ifname"] then
               bss_idx = tonumber(string.match(name, "bss%[(%d)%]"))
             end
           elseif bss_idx >= 0 then
@@ -61,12 +62,12 @@ local function get_wifi_interface_labels()
         end
 
         local labels = {
-          vif = intf['ifname'],
-          ssid = hostapd['ssid'],
-          bssid = hostapd['bssid'],
-          encryption = intf['config']['encryption'], -- In a mixed scenario it would be good to know if A or B was used
-          frequency = hostapd['freq'],
-          channel = hostapd['channel'],
+          vif = intf["ifname"],
+          ssid = hostapd["ssid"],
+          bssid = hostapd["bssid"],
+          encryption = intf["config"]["encryption"], -- In a mixed scenario it would be good to know if A or B was used
+          frequency = hostapd["freq"],
+          channel = hostapd["channel"],
         }
 
         table.insert(interfaces, labels)
@@ -123,7 +124,7 @@ local function scrape()
       metric_hostapd_station_flag_short_preamble(labels, flags["SHORT_PREAMBLE"] and 1 or 0)
 
       metric_hostapd_station_flag_ht(labels, flags["HT"] and 1 or 0)
-      metric_hostapd_station_flag_vht(labels, flags["VHT"]and 1 or 0)
+      metric_hostapd_station_flag_vht(labels, flags["VHT"] and 1 or 0)
       metric_hostapd_station_flag_he(labels, flags["HE"] and 1 or 0)
 
       metric_hostapd_station_flag_wmm(labels, flags["WMM"] and 1 or 0)
@@ -164,8 +165,8 @@ local function scrape()
   end
 
   for _, labels in ipairs(get_wifi_interface_labels()) do
-    local vif = labels['vif']
-    local handle = io.popen("hostapd_cli -i " .. vif .." all_sta")
+    local vif = labels["vif"]
+    local handle = io.popen("hostapd_cli -i " .. vif .. " all_sta")
     local all_sta = handle:read("*a")
     handle:close()
 
index 3ae441474c3af4cdb1f4274a38318a35d3d89af5..5c8f77c998de4f07e412f52e654d2809b607f68d 100644 (file)
@@ -1,12 +1,12 @@
-local ubus = require "ubus"
-local bit = require "bit"
+local ubus = require("ubus")
+local bit = require("bit")
 
 local function get_wifi_hostapd_interfaces(u)
   local ubuslist = u:objects()
   local interfaces = {}
 
-  for _,net in ipairs(ubuslist) do
-    if net.find(net,"hostapd.") then
+  for _, net in ipairs(ubuslist) do
+    if net:find("^hostapd%.") then
       table.insert(interfaces, net)
     end
   end
@@ -35,15 +35,15 @@ local function scrape()
     local label_station = {
       ifname = ifname,
       freq = freq,
-      station = station
+      station = station,
     }
-    local rrm_caps_link_measurement = bit.band(bit.lshift(1, 0), vals['rrm'][1]) > 0 and 1 or 0
-    local rrm_caps_neighbor_report = bit.band(bit.lshift(1, 1), vals['rrm'][1]) > 0 and 1 or 0
-    local rrm_caps_beacon_report_passive = bit.band(bit.lshift(1, 4), vals['rrm'][1]) > 0 and 1 or 0
-    local rrm_caps_beacon_report_active = bit.band(bit.lshift(1, 5), vals['rrm'][1]) > 0 and 1 or 0
-    local rrm_caps_beacon_report_table = bit.band(bit.lshift(1, 6), vals['rrm'][1]) > 0 and 1 or 0
-    local rrm_caps_lci_measurement = bit.band(bit.lshift(1, 4), vals['rrm'][2]) > 0 and 1 or 0
-    local rrm_caps_ftm_range_report = bit.band(bit.lshift(1, 2), vals['rrm'][5]) > 0 and 1 or 0
+    local rrm_caps_link_measurement = bit.band(bit.lshift(1, 0), vals["rrm"][1]) > 0 and 1 or 0
+    local rrm_caps_neighbor_report = bit.band(bit.lshift(1, 1), vals["rrm"][1]) > 0 and 1 or 0
+    local rrm_caps_beacon_report_passive = bit.band(bit.lshift(1, 4), vals["rrm"][1]) > 0 and 1 or 0
+    local rrm_caps_beacon_report_active = bit.band(bit.lshift(1, 5), vals["rrm"][1]) > 0 and 1 or 0
+    local rrm_caps_beacon_report_table = bit.band(bit.lshift(1, 6), vals["rrm"][1]) > 0 and 1 or 0
+    local rrm_caps_lci_measurement = bit.band(bit.lshift(1, 4), vals["rrm"][2]) > 0 and 1 or 0
+    local rrm_caps_ftm_range_report = bit.band(bit.lshift(1, 2), vals["rrm"][5]) > 0 and 1 or 0
 
     metric_hostapd_ubus_station_rrm_caps_link_measurement(label_station, rrm_caps_link_measurement)
     metric_hostapd_ubus_station_rrm_caps_neighbor_report(label_station, rrm_caps_neighbor_report)
@@ -57,10 +57,10 @@ local function scrape()
 
   for _, hostapd_int in ipairs(get_wifi_hostapd_interfaces(u)) do
     local clients_call = u:call(hostapd_int, "get_clients", {})
-    local ifname = hostapd_int:gsub("hostapd.", "")
+    local ifname = hostapd_int:gsub("hostapd%.", "")
 
-    for client, client_table in pairs(clients_call['clients']) do
-      evaluate_metrics(ifname,  clients_call['freq'], client, client_table)
+    for client, client_table in pairs(clients_call["clients"]) do
+      evaluate_metrics(ifname, clients_call["freq"], client, client_table)
     end
   end
   u:close()